package com.ywu.file.sys.standard.service;

import com.ywu.file.sys.standard.config.MinIoConfig;
import com.ywu.file.sys.standard.entity.MinioFileEntity;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
import java.util.UUID;

/**
 * @ClassName YwuMinIoService
 * @Description TODO
 * @Author GroundDemo
 * @Date 2025/7/29 19:08
 * @Version 1.0
 **/
@Service
@DependsOn("minIoConfig")
@Slf4j
public class YwuMinIoService {

    @Autowired
    private MinIoConfig minIoConfig;

    private MinioClient minioClient;

    private final Object lockObj = new Object();

    /**
     * @Author GroundDemo
     * @Description 初始化
     * @Date 20:04 2025/7/29
     * @Param []
     * @return void
     **/
    @PostConstruct
    public void init() throws Exception {
        if (Objects.isNull(minioClient)) {
            synchronized (lockObj) {
                if (Objects.isNull(minioClient)) {
                    minioClient = MinioClient.builder().endpoint(minIoConfig.getUrl()).credentials(minIoConfig.getUser(), minIoConfig.getPassword()).build();
                }
                // 检查存储桶是否存在，不存在则创建
                boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(minIoConfig.getBucket()).build());
                if (!bucketExists) {
                    minioClient.makeBucket(MakeBucketArgs.builder().bucket(minIoConfig.getBucket()).build());
                }
                // 校验上传文件夹是否存在
                String uploadTempDir = minIoConfig.getUploadTempDir() + File.separator + minIoConfig.getBucket();
                File file = new File(uploadTempDir);
                if (!file.exists()) {
                    // 文件夹不存在，则创建文件夹
                    boolean res = file.mkdirs();
                    if (!res) {
                        throw new RuntimeException("mkdir error!!!");
                    }
                }
                String downloadTempDir = minIoConfig.getDownloadTempDir() + File.separator + minIoConfig.getBucket();
                File downloadFile = new File(downloadTempDir);
                if (!downloadFile.exists()) {
                    // 文件夹不存在，则创建文件夹
                    boolean res = downloadFile.mkdirs();
                    if (!res) {
                        throw new RuntimeException("mkdir error!!!");
                    }
                }
            }
        }
    }

    /**
     * @Author GroundDemo
     * @Description 上传文件
     * @Date 20:04 2025/7/29
     * @Param [fileName, filePath]
     * @return com.ywu.file.sys.standard.entity.MinioFileEntity
     **/
    public MinioFileEntity uploadFile(String fileName, String filePath) {
        // 上传文件到MinIO
        String uniqueFileName = null;
        String extension = null;
        String contentType = null;
        try {
            if (StringUtils.isEmpty(fileName)) {
                throw new IllegalArgumentException("文件名称不能为空");
            }
            extension = fileName.substring(fileName.lastIndexOf("."));
            uniqueFileName = fileName + "-" + UUID.randomUUID() + extension;
            Path path = Paths.get(filePath);
            contentType = Files.probeContentType(path);
            minioClient.uploadObject(
                    UploadObjectArgs.builder()
                            .bucket(minIoConfig.getBucket())
                            .object(uniqueFileName)           // 对象名称（即文件路径）
                            .filename(filePath)               // 本地文件路径
                            .contentType(contentType)
                            .build());
        } catch (Exception e) {
            log.error("upload file error {} - {}", filePath, fileName);
            throw new RuntimeException("upload file error");
        }
        File file = new File(filePath);
        MinioFileEntity minioFileEntity = new MinioFileEntity();
        minioFileEntity.setMinioObjectName(uniqueFileName);
        minioFileEntity.setFileName(fileName);
        minioFileEntity.setBucketName(minIoConfig.getBucket());
        minioFileEntity.setFileSize(String.valueOf(file.length()));
        minioFileEntity.setFileSuffix(extension.substring(1));
        minioFileEntity.setFileType(contentType);
        // 删除本地文件
        file.delete();
        return minioFileEntity;
    }

    /**
     * @Author GroundDemo
     * @Description 上传文件
     * @Date 20:04 2025/7/29
     * @Param [file]
     * @return com.ywu.file.sys.standard.entity.MinioFileEntity
     **/
    public MinioFileEntity uploadFile(MultipartFile file) {
        if (file.isEmpty()) {
            throw new IllegalArgumentException("上传文件不能为空");
        }
        // 生成唯一文件名（避免重复）
        String originalFilename = file.getOriginalFilename();
        if (StringUtils.isEmpty(originalFilename)) {
            throw new IllegalArgumentException("文件名称不能为空");
        }
        String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
        String uniqueFileName = originalFilename + "-" + UUID.randomUUID() + extension;
        // 将对象存储为临时文件
        File tempFile = null;
        try {
            tempFile = File.createTempFile("minio-", uniqueFileName, new File(minIoConfig.getUploadTempDir() + File.separator + minIoConfig.getBucket()));
            file.transferTo(tempFile);
        } catch (Exception e) {
            log.error("文件转储失败");
            throw new RuntimeException(e);
        }
        try {
            // 上传文件到MinIO
            minioClient.uploadObject(
                    UploadObjectArgs.builder().bucket(minIoConfig.getBucket()).object(uniqueFileName)
                            .filename(tempFile.getAbsolutePath()).contentType(file.getContentType())
                            .build()
            );
        } catch (Exception e) {
            log.error("文件上传失败");
            throw new RuntimeException(e);
        } finally {
            // 删除临时文件
            if (!tempFile.delete()) {
                log.error("删除临时文件失败，{}", minIoConfig.getUploadTempDir() + File.separator + uniqueFileName);
            }
        }
        // 构建返回对象
        MinioFileEntity minioFileEntity = new MinioFileEntity();
        minioFileEntity.setFileName(originalFilename);
        minioFileEntity.setMinioObjectName(uniqueFileName);
        minioFileEntity.setBucketName(minIoConfig.getBucket());
        minioFileEntity.setFileSize(String.valueOf(file.getSize()));
        minioFileEntity.setFileSuffix(extension.substring(1));
        minioFileEntity.setFileType(file.getContentType());
        return minioFileEntity;
    }

    /**
    * @Author GroundDemo
    * @Description 下载文件
    * @Date 20:08 2025/7/29
    * @Param [bucketName, objectName, savePath]
    * @return void
    **/
    public void downloadFile(String objectName, String savePath) {
        try {
            minioClient.downloadObject(DownloadObjectArgs.builder().bucket(minIoConfig.getBucket()).object(objectName).filename(savePath).build());
        } catch (Exception e) {
            log.error("download file error !!! {}", e);
            throw new RuntimeException("download file error !!!");
        }
    }

    /**
    * @Author GroundDemo
    * @Description 删除文件
    * @Date 20:12 2025/7/29
    * @Param [bucketName, objectName]
    * @return void
    **/
    public void deleteFile(String objectName) {
        try {
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(minIoConfig.getBucket()).object(objectName).build());
        } catch (Exception e) {
            log.error("delete file error !!!");
            throw new RuntimeException("delete file error !!!");
        }
    }
}
